package com.yuns.model.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.yuns.company.entity.CompanyInfoBase;
import com.yuns.company.entity.CompanyUserBase;
import com.yuns.company.entity.CompanyUserRel;
import com.yuns.company.mapper.CompanyUserBaseMapper;
import com.yuns.company.service.ICompanyUserBaseService;
import com.yuns.company.service.ICompanyUserRelService;
import com.yuns.company.service.impl.CompanyUserBaseServiceImpl;
import com.yuns.exception.MyException;
import com.yuns.mas.platform.business.SiMockStub;
import com.yuns.mas.platform.schema.sms.MessageFormat;
import com.yuns.mas.platform.schema.sms.SendMethodType;
import com.yuns.mas.platform.schema.sms.SendSmsRequest;
import com.yuns.mas.platform.schema.sms.SendSmsResponse;
import com.yuns.model.entity.*;
import com.yuns.model.mapper.SysUserMapper;
import com.yuns.model.service.*;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.yuns.util.*;
import com.yuns.web.dto.CompanyUserRegParam;
import com.yuns.web.param.*;
import com.yuns.web.sys.param.LoginParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.net.URL;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author luwenchao
 * @since 2018-08-01
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private static final Logger logger = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Autowired
    private SysDictService sysDictService;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Autowired
    private SysDeptService sysDeptService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private ICompanyUserBaseService companyUserBaseService;

    @Resource
    private ICompanyUserRelService companyUserRelService;

    private static final String KEY_PREFIX = "user:verify:phone";

    @Value("${sms.MasWsUrl}")
    private String MasWsUrl;

    @Value("${sms.ApplicationID}")
    private String ApplicationID;

    @Value("${sms.ExtendCode}")
    private String ExtendCode;

    @Value("${sms.MessageTextFormat}")
    private String MessageTextFormat;

    @Value("${sms.SendMethod}")
    private String SendMethod;

    @Value("${sms.DeliveryResultRequest}")
    private String DeliveryResultRequest;


    @Override
    public void createSysUser(LoginParam sysUser) {
        SysUser user = new SysUser();

        user.setPhone(sysUser.getPhone());
        user.setPassword(sysUser.getPwd());
        user.setUserName(sysUser.getName());
        user.setLatitude(sysUser.getLatitude());
        user.setLongitude(sysUser.getLongitude());
        user.setType(Constants.TYPE_1);
        user.setCreatedBy(Constants.XXB);
        user.setCreatedDate(new Date());
        user.setStatus(Constants.STUTAS_1);
        sysUserMapper.insert(user);
    }

    /**
     * 根据部门id查询管理用户
     */
    @Override
    public List<SysUser> queryUserBySysDeptId(Integer id) {
        return baseMapper.queryUserBySysDeptId(id);
    }

    @Override
    public List<SysUser> selectUserList(Page<SysUser> page , FrontPage<SysUser> frontPage) {
        List<SysUser> sysUsers = baseMapper.selectUserList(page,frontPage);
        sysUsers.forEach(x -> {
            List<SysUserRole> sysUserRoles = sysUserRoleService.selectUserRoleList(x.getId());
            List<Long> longs = new ArrayList<>();
            List<Integer> integers = new ArrayList<>();
            sysUserRoles.forEach(y -> {
                longs.add(y.getRoleId());
            });
            x.setRoleIds(longs);
            x.setServiceIds(integers);
            x.setSysUserRoles(sysUserRoles);
        });

        return sysUsers;
    }

    @Override
    public List<SysDept> selectSysDeptUserList() {
        List<SysUser> sysUsers = baseMapper.selectUserList(null,null);
        List<SysDept> sysDepts = sysDeptService.selectSysDeptList();
        findSysUsers(sysDepts, sysUsers);
        return sysDepts;
    }

    @Override
    @Transactional
    public boolean insertSysUser(SysUser entity) {
        SysUser sysUser = new SysUser();
        sysUser.setAccount(entity.getAccount());
        sysUser = baseMapper.selectOne(sysUser);
        if (sysUser != null) {
            throw new MyException("当前账号已经存在");
        }
        //企业用户表新增
        CompanyUserBase companyUserBase=new CompanyUserBase();
        companyUserBase.setUserName(entity.getUserName());
        companyUserBase.setNickname(entity.getUserName());
        companyUserBase.setIdCard(entity.getBrithId());
        companyUserBase.setJob("环保局员工");
        companyUserBase.setUserType(4);
        companyUserBase.setWechat(entity.getWechat());
        companyUserBase.setIdCard(entity.getBrithId());
        companyUserBase.setTel(entity.getPhone());
        companyUserBase.setUserStatus(Integer.parseInt(entity.getStatus()));
        companyUserBase.setEmail(entity.getEmail());
        companyUserBaseService.insert(companyUserBase);

        //查询当前账户是否重复
        entity.setInstrument(companyUserBase.getId().toString());
        baseMapper.insert(entity);
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(entity.getId().longValue());
        sysUserRole.setRoleId(0L);
        return sysUserRoleService.insert(sysUserRole);
    }

    private void findSysUsers(List<SysDept> sysDepts, List<SysUser> sysUsers) {
        sysDepts.forEach(x -> {
            sysUsers.forEach(y -> {
                if (y.getDeptId() != null && (y.getDeptId() + "").equals(x.getId() + "")) {
                    if (x.getUserChildren() != null) {
                        x.getUserChildren().add(y);
                    } else {
                        List<SysUser> users = new ArrayList<>();
                        users.add(y);
                        x.setUserChildren(users);
                    }
                }

            });
            if (x.getChildren().size() != 0) {
                findSysUsers(x.getChildren(), sysUsers);
            }
        });
    }

    /**
     * 检查账号
     *
     * @param data
     * @param type
     * @return
     */
    public Boolean checkData(String data, Integer type) {
        SysUser user = new SysUser();
        switch (type) {
            case 1:
                user.setUserName(data);
                break;
            case 2:
                user.setPhone(data);
                break;
            default:
                throw new RuntimeException("无效用户参数类型");
        }
        EntityWrapper wrapper = new EntityWrapper();
        wrapper.setEntity(user);
        return sysUserMapper.selectCount(wrapper) == 0;
    }

    /**
     * 发送短信
     *
     * @param phone
     */
    @Override
    public void sendCode(String phone) {
        //生成key
        String key = KEY_PREFIX + phone;
        //生成验证码
        String code = NumberUtils.generateCode(6);

        Map<String, String> msg = new HashMap<>();
        msg.put("phone", phone);
        msg.put("code", code);

        //发送验证码
        String message ="你好,你的验证码是:"+code+",有效时间5分钟";
//        this.sendSms(phone,message);

        //保存验证码
        redisTemplate.boundValueOps(key).set(code,5,TimeUnit.MINUTES);
        System.out.println("############# phone=" + phone +";code="+code);
    }

    public String sendSms(String phone,String message) {

        String requestIdentifier = "";

        URL url;
        try {
            url = new URL(MasWsUrl);
            org.apache.axis.client.Service service = new org.apache.axis.client.Service();
            SiMockStub stub = new SiMockStub(url, service);

            SendSmsRequest s = new SendSmsRequest();
            s.setApplicationID(ApplicationID);
            s.setDeliveryResultRequest(Boolean.parseBoolean(DeliveryResultRequest));
            s.setExtendCode(ExtendCode);

            s.setMessage(new String(message.getBytes("utf-8"), "utf-8"));
            System.out.println(new String(message.getBytes("utf-8"), "utf-8"));
            s.setMessageFormat(MessageFormat.fromValue(MessageTextFormat));
            s.setSendMethod(SendMethodType.fromValue(SendMethod));
            String[] a = ("tel:"+phone).split(";");
            int leng = a.length;
            org.apache.axis.types.URI[] ary = new org.apache.axis.types.URI[leng];
            for (int i = 0; i < leng; i++) {
                org.apache.axis.types.URI temp = new org.apache.axis.types.URI(a[i]);
                ary[i] = temp;
            }
            s.setDestinationAddresses(ary);

            SendSmsResponse rep = stub.sendSms(s);
            requestIdentifier = rep.getRequestIdentifier();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("requestIdentifier=" + requestIdentifier);
        return requestIdentifier;
    }

    /**
     * 手机号注册
     *
     * @param user
     * @return
     */
    @Transactional
    public Object registerByTel(SysUser user) {
        String key = KEY_PREFIX + user.getPhone();
        // 从redis取出验证码
        String codeCache = (String)redisTemplate.opsForValue().get(key);
        String code=user.getCode();
        // 检查验证码是否正确
        if (code==null || !code.equals(codeCache)) {
            // 不正确，返回
            logger.info("[用户注册]：验证码不正确");
            return ResultJson.error(ExceptionEnum.CODE_ERROR.getMsg());
        }
        // 生成盐
        String salt = CodecUtils.generateSalt();
        user.setSalt(salt);
        // 对密码进行加密
        user.setPassword(user.getPassword());
        //手机号注册属于个人用户
        CompanyUserBase companyUserBase = new CompanyUserBase();
        companyUserBase.setUserName(user.getUserName());
        companyUserBase.setNickname(user.getAccount());
        companyUserBase.setTel(user.getPhone());
        companyUserBase.setIdCard(user.getBrithId());
        companyUserBase.setWechat(user.getWechat());
        companyUserBase.setUserType(3);
        companyUserBase.setUserStatus(0);
        companyUserBaseService.insert(companyUserBase);

        // 写入数据库
        user.setInstrument(companyUserBase.getId().toString());
        boolean boo = sysUserMapper.insert(user) == 1;
        // 如果注册成功，删除redis中的code
        if (boo) {
            try {
                redisTemplate.delete(key);
            } catch (Exception e) {
                logger.error("删除缓存验证码失败，code：{}", code, e);
                return ResultJson.error(ExceptionEnum.UNKNOWN_MISTAKE.getMsg());
            }
        }
        logger.info("[用户注册]：注册成功！");
        return ResultJson.ok();
    }


    /**
     * 企业用户注册
     *
     * @param param
     * @return
     */
    @Transactional
    @Override
    public Object register(CompanyUserRegParam param) {
        //对手机号进行校验
        String tel = param.getTel();
        SysUser record = new SysUser();
        record.setPhone(tel);
        SysUser user = sysUserMapper.selectOne(record);
        if (user == null) {
            record.setPhone(null);
            record.setAccount(param.getNickname());
            user = sysUserMapper.selectOne(record);
            if(user != null){
                return ResultJson.error(ExceptionEnum.ACCOUNT_NOT_REPEAT.getMsg());
            }

            CompanyUserBase companyUserBase = new CompanyUserBase();
            companyUserBase.setUserName(param.getUserName());
            companyUserBase.setNickname(param.getNickname());
            companyUserBase.setJob(param.getJob());
            companyUserBase.setTel(param.getTel());
            companyUserBase.setIdCard(param.getIdCard());
            companyUserBase.setWechat(param.getWechat());
            companyUserBase.setUserType(0);
            companyUserBase.setUserStatus(0);
            boolean flag = companyUserBaseService.insert(companyUserBase);
            if (flag) {
                CompanyUserRel companyUserRel = new CompanyUserRel();
                companyUserRel.setCompanyId(param.getCompanyId());
                companyUserRel.setCompanyUserId(companyUserBase.getId());
                companyUserRelService.insert(companyUserRel);
                //更新sys_user表
                String salt = CodecUtils.generateSalt(); // 生成盐
                SysUser sysUser = new SysUser();
                sysUser.setAccount(param.getNickname());
                sysUser.setUserName(param.getUserName());
                sysUser.setPassword(param.getPassword());
                sysUser.setPhone(param.getTel());
                sysUser.setType(0);
                sysUser.setStatus("0");
                sysUser.setSalt(salt);
                sysUser.setInstrument(companyUserBase.getId().toString());
                sysUserMapper.insert(sysUser);
                return ResultJson.ok();
            } else {
                return ResultJson.error(ExceptionEnum.UNKNOWN_MISTAKE.getMsg());
            }
        } else {
            return ResultJson.error(ExceptionEnum.PHONE_NOT_REPEAT.getMsg());
        }
    }

    /**
     * 账号登录
     *
     * @param username
     * @param password
     * @return
     */
    public Object accountLogin(String username, String password) {
        // 查询
        SysUser record = new SysUser();
        record.setUserName(username);
        SysUser user = sysUserMapper.selectOne(record);
        // 校验用户名
        if (user == null) {
            return  ResultJson.error(ExceptionEnum.USERNAME_ERROR.getMsg());
        }
        // 校验密码
        if (!user.getPassword().equals(password)) {
            return  ResultJson.error(ExceptionEnum.PASSWORD_ERROR.getMsg());
        }
        // 用户名密码都正确
        String companyUserId = user.getInstrument();
        CompanyUserBase companyUserBase = companyUserBaseService.selectById(Integer.parseInt(companyUserId));
        return ResultJson.ok(companyUserBase);
    }

    /**
     * 手机号登录
     *
     * @param tel
     * @param code
     * @return
     */
    @Override
    public Object telLogin(String tel, String code) {
        String key = KEY_PREFIX + tel;
        // 从redis取出验证码
        String codeCache = (String)redisTemplate.opsForValue().get(key);
        // 检查验证码是否正确
        if (!code.equals(codeCache)) {
            // 不正确，返回
            logger.info("[用户登录失败]：验证码不正确");
            return ResultJson.error(ExceptionEnum.CODE_ERROR.getMsg());
        }
        SysUser record = new SysUser();
        record.setPhone(tel);
        SysUser user = sysUserMapper.selectOne(record);
        if (user == null) {
            logger.info("[用户登录失败]：无此用户");
            return ResultJson.error(ExceptionEnum.USERNAME_ERROR.getMsg());
        }
        //根据用户名查询用户账号是否正常
        CompanyUserBase userBase = companyUserBaseService.selectById(Integer.parseInt(user.getInstrument()));
        if (userBase == null) {
            return ResultJson.error(ExceptionEnum.USERNAME_ERROR.getMsg());
        } else {
            //判断用户状态是否正常
            if (userBase.getUserStatus() == 0 && userBase.getDel() == 0) {
                return ResultJson.ok(userBase);
            } else {
                logger.info("[用户登录失败]：用户状态不正常");
                return  ResultJson.error(ExceptionEnum.USERNAME_ERROR.getMsg());
            }
        }
    }

}
